home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / gnu_oleo_1_2_2.lha / oleo-1.2.2 / io-utils.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  20KB  |  1,097 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <math.h>
  22. #include "sysdef.h"
  23. #include "io-utils.h"
  24. #include "cell.h"
  25. #include "io-generic.h"
  26. #include "io-abstract.h"
  27. #include "lists.h"
  28.  
  29.  
  30.  
  31. extern unsigned short default_width;
  32. extern unsigned short default_height;
  33. extern unsigned short saved_default_width;
  34. extern unsigned short saved_default_height;
  35.  
  36. extern CELLREF curow, cucol;
  37. extern struct rng screen;
  38. extern int default_fmt;
  39.  
  40.  
  41. /* Routines for formatting cell values */
  42. #ifdef __STDC__
  43. struct user_fmt;
  44. static char *pr_flt (double, struct user_fmt *, int);
  45. static char *pr_int (long, struct user_fmt *, int);
  46. #else
  47. static char *pr_flt ();
  48. static char *pr_int ();
  49. #endif
  50.  
  51.  
  52. /* Constants */
  53. char *bname[] =
  54. {
  55.   "#FALSE", "#TRUE"
  56. };
  57.  
  58. char numb_oflo[] = "########################################";
  59.  
  60. double __plinf;
  61. double __neinf;
  62. double __nan;
  63.  
  64. char nname[] = "#NOT_A_NUMBER";
  65. char iname[] = "#INFINITY";
  66. char mname[] = "#MINUS_INFINITY";
  67.  
  68. static double
  69. divide (a, b)
  70.      double a;
  71.      double b;
  72. {
  73.   return a / b;
  74. }
  75.  
  76. static RETSIGTYPE
  77. ignore_sig (sig)
  78.      int sig;
  79. {
  80.   (void)signal (SIGFPE, ignore_sig);
  81. }
  82.  
  83. /* It's ok of this fails and generates signals.  In that case, 
  84.  * the same signal will occur when evaluating formulas and a
  85.  * (less informative) error value substituted.  Note that this 
  86.  * should be called before init_eval.
  87.  */
  88. #ifdef __STDC__
  89. void
  90. init_infinity (void)
  91. #else
  92. void
  93. init_infinity ()
  94. #endif
  95. {
  96.   (void)signal (SIGFPE, ignore_sig);
  97.   __plinf = divide (1., 0.);
  98.   __neinf = divide (-1., 0.);
  99.   __nan = __plinf + __neinf;
  100. }
  101.  
  102.  
  103.  
  104. /* Slightly larger than the maximum exponent we ever expect to see */
  105. #define BIGFLT 309
  106. #ifdef TEST
  107. char print_buf[1024 * 8];
  108. #else
  109. char print_buf[BIGFLT + 20];
  110. #endif
  111.  
  112.  
  113.  
  114. /* Structures/vars/functions for dealing with formatting floating-point
  115.    numbers, etc */
  116.  
  117. struct user_fmt
  118.   {
  119.     char *p_hdr, *n_hdr;
  120.     char *p_trl, *n_trl;
  121.     char *zero, *comma, *decpt;
  122.     unsigned char prec;
  123.     double scale;
  124.   };
  125.  
  126.  
  127. struct user_fmt dol =
  128. {
  129.   "$", "($", 0, ")", "$0", ",", ".", PRC_FLT, 1};
  130.  
  131. struct user_fmt cma =
  132. {
  133.   0, "(", 0, ")", "0", ",", ".", PRC_FLT, 1};
  134.  
  135. struct user_fmt pct =
  136. {
  137.   0, "-", "%", "%", "0%", 0, ".", PRC_FLT, 100};
  138.  
  139. struct user_fmt fxt =
  140. {
  141.   0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1};
  142.  
  143. /* Variables */
  144.  
  145. struct user_fmt u[16] =
  146. {
  147.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  148.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  149.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  150.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  151.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  152.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  153.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  154.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  155.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  156.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  157.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  158.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  159.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  160.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  161.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  162.   {0, "-", 0, 0, "0", 0, ".", PRC_FLT, 1},
  163. };
  164.  
  165.  
  166. /* Turn a floating-point number into the canonical text form.  This scribbles
  167.    on print_buf */
  168. char *
  169. flt_to_str (val)
  170.      double val;
  171. {
  172.   double f;
  173.  
  174.   if (val == __plinf)
  175.     return iname;
  176.   if (val == __neinf)
  177.     return mname;
  178.   f = fabs (val);
  179.   if (f >= 1e6 || (f > 0 && f <= 9.9999e-6))
  180.     {
  181.       sprintf (print_buf, "%e", val);
  182.       return print_buf;
  183.     }
  184.   return pr_flt (val, &fxt, PRC_FLT);
  185. }
  186.  
  187. /* create the human-readable version of the contents of a cell
  188.    This scribbles on print-buf bigtime */
  189.  
  190. char *
  191. print_cell (cp)
  192.      CELL *cp;
  193. {
  194.   int j;
  195.   int p;
  196.   long num;
  197.   static char zeroes[] = "000000000000000";
  198.  
  199.   j = GET_FMT (cp);
  200.  
  201.   if (j == FMT_DEF)
  202.     j = default_fmt;
  203.   if (j == FMT_HID || GET_TYP (cp) == 0)
  204.     return "";
  205.  
  206.   if (GET_TYP (cp) == TYP_STR)
  207.     return cp->cell_str;
  208.   if (GET_TYP (cp) == TYP_BOL)
  209.     {
  210. #ifdef TEST
  211.       if (cp->cell_bol < 0 || cp->cell_bol > 1)
  212.     panic ("Bool %d out of range", cp->cell_bol);
  213. #endif
  214.       return bname[cp->cell_bol];
  215.     }
  216.   if (GET_TYP (cp) == TYP_ERR)
  217.     {
  218. #ifdef TEST
  219.       if (cp->cell_err > ERR_MAX || cp->cell_err < 0)
  220.     panic ("Error %d out of range", cp->cell_err);
  221. #endif
  222.       return ename[cp->cell_err];
  223.     }
  224.   if (GET_TYP (cp) == TYP_FLT)
  225.     {
  226.       p = GET_PRC (j);
  227.       switch (j | PRC_FLT)
  228.     {
  229.     case FMT_GPH:
  230.       if (cp->cell_flt < 0)
  231.         {
  232.           j = '-';
  233.           num = -(cp->cell_flt);
  234.         }
  235.       else if (cp->cell_flt >= 1)
  236.         {
  237.           j = '+';
  238.           num = (cp->cell_flt);
  239.         }
  240.       else
  241.         {
  242.           j = '0';
  243.           num = 1;
  244.         }
  245.     graph:
  246.       if (num >= sizeof (print_buf))
  247.         {
  248.           io_error_msg ("Cannot graph %d '%c'", p, j);
  249.           num = sizeof (print_buf) - 1;
  250.         }
  251.       print_buf[num] = '\0';
  252.       while (--num >= 0)
  253.         print_buf[num] = j;
  254.       return print_buf;
  255.  
  256.     case FMT_USR:
  257.       return pr_flt (cp->cell_flt, &u[p], u[p].prec);
  258.  
  259.     case FMT_GEN:
  260.       {
  261.         double f;
  262.  
  263.         f = fabs (cp->cell_flt);
  264.         if (f >= 1e6 || (f > 0 && f <= 9.9999e-6))
  265.           goto handle_exp;
  266.         return pr_flt (cp->cell_flt, &fxt, p);
  267.       }
  268.  
  269.     case FMT_DOL:
  270.       return pr_flt (cp->cell_flt, &dol, p);
  271.  
  272.     case FMT_CMA:
  273.       return pr_flt (cp->cell_flt, &cma, p);
  274.  
  275.     case FMT_PCT:
  276.       return pr_flt (cp->cell_flt, &pct, p);
  277.  
  278.     case FMT_FXT:
  279.       return pr_flt (cp->cell_flt, &fxt, p);
  280.  
  281.     case FMT_EXP:
  282.     handle_exp:
  283.       if (cp->cell_flt == __plinf)
  284.         return iname;
  285.       if (cp->cell_flt == __neinf)
  286.         return mname;
  287.       if (p == PRC_FLT)
  288.         sprintf (print_buf, "%e", cp->cell_flt);
  289.       else
  290.         sprintf (print_buf, "%.*e", p, cp->cell_flt);
  291.       return print_buf;
  292. #ifdef TEST
  293.     default:
  294.       panic ("Unknown format %d", j);
  295.       return 0;
  296. #endif
  297.     }
  298.     }
  299.  
  300.   if (GET_TYP (cp) == TYP_INT)
  301.     {
  302.       p = GET_PRC (j);
  303.       switch (j | PRC_FLT)
  304.     {
  305.     case FMT_GPH:
  306.       if (cp->cell_int < 0)
  307.         {
  308.           j = '-';
  309.           num = -(cp->cell_int);
  310.         }
  311.       else if (cp->cell_int >= 1)
  312.         {
  313.           j = '+';
  314.           num = (cp->cell_int);
  315.         }
  316.       else
  317.         {
  318.           j = '0';
  319.           num = 1;
  320.         }
  321.       goto graph;
  322.  
  323.     case FMT_USR:
  324.       return pr_int (cp->cell_int, &u[p], u[p].prec);
  325.  
  326.     case FMT_GEN:
  327.       sprintf (print_buf, "%ld", cp->cell_int);
  328.       return print_buf;
  329.  
  330.     case FMT_DOL:
  331.       return pr_int (cp->cell_int, &dol, p);
  332.  
  333.     case FMT_CMA:
  334.       return pr_int (cp->cell_int, &cma, p);
  335.  
  336.     case FMT_PCT:
  337.       return pr_int (cp->cell_int, &pct, p);
  338.  
  339.     case FMT_FXT:
  340.       if (p != PRC_FLT && p != 0)
  341.         sprintf (print_buf, "%ld.%.*s", cp->cell_int, p, zeroes);
  342.       else
  343.         sprintf (print_buf, "%ld", cp->cell_int);
  344.       return print_buf;
  345.  
  346.     case FMT_EXP:
  347.       if (p != PRC_FLT)
  348.         sprintf (print_buf, "%.*e", p, (double) (cp->cell_int));
  349.       else
  350.         sprintf (print_buf, "%e", (double) (cp->cell_int));
  351.       return print_buf;
  352. #ifdef TEST
  353.     default:
  354.       panic ("Unknown format %d", j);
  355.       return 0;
  356. #endif
  357.     }
  358.     }
  359. #ifdef TEST
  360.   panic ("Unknown cell type %d", GET_TYP (cp));
  361. #endif
  362.   return 0;
  363. }
  364.  
  365. /* Return the value of ROW,COL in a human-readable fashion
  366.    In paticular, strings have "" around them, and are \\ed
  367.  */
  368. #if __STDC__
  369. char *
  370. cell_value_string (CELLREF row, CELLREF col)
  371. #else
  372. char *
  373. cell_value_string (row, col)
  374.      CELLREF row;
  375.      CELLREF col;
  376. #endif
  377. {
  378.   CELL *cp;
  379.  
  380.   cp = find_cell (row, col);
  381.   if (!cp || !GET_TYP (cp))
  382.     return "";
  383.   switch (GET_TYP (cp))
  384.     {
  385.     case TYP_FLT:
  386.       return flt_to_str (cp->cell_flt);
  387.  
  388.     case TYP_INT:
  389.       sprintf (print_buf, "%ld", cp->cell_int);
  390.       return print_buf;
  391.  
  392.     case TYP_STR:
  393.       return backslash_a_string (cp->cell_str, 1);
  394.  
  395.     case TYP_BOL:
  396.       return bname[cp->cell_bol];
  397.  
  398.     case TYP_ERR:
  399.       return ename[cp->cell_err];
  400. #ifdef TEST
  401.     default:
  402.       panic ("unknown type %d in cell_value_string", GET_TYP (cp));
  403. #endif
  404.     }
  405.   return 0;
  406. }
  407.  
  408. static char *
  409. pr_int (val, fmt, prec)
  410.      long val;
  411.      struct user_fmt *fmt;
  412.      int prec;
  413. {
  414.   char *pf, *pff, *pt;
  415.   long int n;
  416.   int nn = 0;
  417.  
  418.   pt = &print_buf[sizeof (print_buf) - 1];
  419.   *pt = '\0';
  420.  
  421.   n = fmt->scale * ((val < 0) ? -val : val);
  422.   if (n == 0)
  423.     return fmt->zero ? fmt->zero : "";
  424.  
  425.   pf = pff = (val < 0) ? fmt->n_trl : fmt->p_trl;
  426.   if (pf && *pf)
  427.     {
  428.       while (*pf)
  429.     pf++;
  430.       do
  431.     *--pt = *--pf;
  432.       while (pf != pff);
  433.     }
  434.  
  435.   if (prec != PRC_FLT && prec != 0)
  436.     {
  437.       while (prec-- > 0)
  438.     *--pt = '0';
  439.       pf = pff = fmt->decpt;
  440.       if (pf)
  441.     {
  442.       while (*pf)
  443.         pf++;
  444.       do
  445.         *--pt = *--pf;
  446.       while (pf != pff);
  447.     }
  448.       /* *--pt='.'; */
  449.     }
  450.   do
  451.     {
  452.       *--pt = (n % 10) + '0';
  453.       n /= 10;
  454.       if (nn++ == 2 && n > 0)
  455.     {
  456.       if (fmt->comma && *(fmt->comma))
  457.         {
  458.           for (pf = pff = fmt->comma; *pf; pf++)
  459.         ;
  460.           do
  461.         *--pt = *--pf;
  462.           while (pf != pff);
  463.         }
  464.       nn = 0;
  465.     }
  466.     }
  467.   while (n > 0);
  468.  
  469.   pf = pff = (val < 0) ? fmt->n_hdr : fmt->p_hdr;
  470.   if (pf && *pf)
  471.     {
  472.       while (*pf)
  473.     pf++;
  474.       do
  475.     *--pt = *--pf;
  476.       while (pf != pff);
  477.     }
  478.   return pt;
  479. }
  480.  
  481. static char *
  482. pr_flt (val, fmt, prec)
  483.      double val;
  484.      struct user_fmt *fmt;
  485.      int prec;
  486. {
  487.   char *iptr;
  488.   char *fptr;
  489.   char *pptr;
  490.   char *pf, *pff;
  491.   double fract, integer, tmpval;
  492.   int n;
  493.   int isneg;
  494.   int comlen;
  495.  
  496.   val *= fmt->scale;
  497.  
  498.   if (val == __plinf)
  499.     return iname;
  500.   if (val == __neinf)
  501.     return mname;
  502.   if (val != val)
  503.     return nname;
  504.  
  505.   iptr = &print_buf[BIGFLT];
  506.   fptr = &print_buf[BIGFLT];
  507.  
  508.  
  509.   if (val == 0)
  510.     return fmt->zero ? fmt->zero : "";
  511.  
  512.   if (val < 0)
  513.     {
  514.       isneg = 1;
  515.       val = -val;
  516.     }
  517.   else
  518.     isneg = 0;
  519.  
  520.   comlen = 0;
  521.   if (fmt->comma && *(fmt->comma))
  522.     for (pf = fmt->comma; *pf; comlen++, pf++)
  523.       ;
  524.  
  525.   fract = modf (val, &integer);
  526.   n = 0;
  527.   do
  528.     {
  529.       if (iptr < &print_buf[comlen])
  530.     return numb_oflo;
  531.       tmpval = modf (integer / 10, &integer);
  532.       *--iptr = '0' + (int) ((tmpval + .01) * 10);
  533.       if (comlen && n++ == 2 && integer)
  534.     {
  535.       n = 0;
  536.       pff = fmt->comma;
  537.       pf = pff + comlen;
  538.       do
  539.         *--iptr = *--pf;
  540.       while (pf != pff);
  541.     }
  542.     }
  543.   while (integer);
  544.  
  545.   if (prec)
  546.     {
  547.       int p1;
  548.  
  549.       p1 = (prec == PRC_FLT) ? 15 : (prec > 0) ? prec : -prec;
  550.       pf = fmt->decpt;
  551.       while (pf && *pf)
  552.     *fptr++ = *pf++;
  553.       /* *fptr++='.'; */
  554.       if (fract)
  555.     {
  556.       do
  557.         {
  558.           fract = modf (fract * 10, &tmpval);
  559.           *fptr++ = '0' + (int) tmpval;
  560.         }
  561.       while (--p1 && fract);
  562.     }
  563.       if (prec > 0 && prec != PRC_FLT)
  564.     while (p1--)
  565.       *fptr++ = '0';
  566.       else
  567.     {
  568.       fract = 0;
  569.       while (fptr[-1] == '0')
  570.         --fptr;
  571.       while (!isdigit (fptr[-1]))
  572.         --fptr;
  573.       *fptr = '\0';
  574.     }
  575.     }
  576.   if (fract)
  577.     {
  578.       (void) modf (fract * 10, &tmpval);
  579.       if (tmpval > 4)
  580.     {
  581.       iptr[-1] = '0';
  582.       for (pptr = fptr - 1;; --pptr)
  583.         {
  584.           if (!isdigit (*pptr))
  585.         continue;
  586.           else if (*pptr == '9')
  587.         {
  588.           if (pptr == fptr - 1 && pptr > &print_buf[BIGFLT] && (prec < 0 || prec == PRC_FLT))
  589.             {
  590.               --fptr;
  591.               while (!isdigit (pptr[-1]))
  592.             {
  593.               --fptr;
  594.               --pptr;
  595.             }
  596.               *pptr = '\0';
  597.             }
  598.           else
  599.             *pptr = '0';
  600.         }
  601.           else
  602.         {
  603.           (*pptr)++;
  604.           break;
  605.         }
  606.         }
  607.       if (pptr < iptr)
  608.         {
  609.           --iptr;
  610.           if (n == 3)
  611.         {
  612.           char tmpch;
  613.  
  614.           tmpch = *iptr++;
  615.           for (pf = pff = fmt->comma; *pf; pf++)
  616.             ;
  617.           do
  618.             *--iptr = *--pf;
  619.           while (pf != pff);
  620.           *--iptr = tmpch;
  621.         }
  622.         }
  623.     }
  624.     }
  625.   pf = pff = (isneg) ? fmt->n_hdr : fmt->p_hdr;
  626.   if (pf && *pf)
  627.     {
  628.       while (*pf)
  629.     pf++;
  630.       do
  631.     *--iptr = *--pf;
  632.       while (pf != pff);
  633.     }
  634.  
  635.   pf = (isneg) ? fmt->n_trl : fmt->p_trl;
  636.   while (pf && *pf)
  637.     *fptr++ = *pf++;
  638.   *fptr = 0;
  639.   return iptr;
  640. }
  641.  
  642. char *
  643. adjust_prc (oldp, cp, width, smallwid, just)
  644.      char *oldp;
  645.      CELL *cp;
  646.      int width;
  647.      int smallwid;
  648.      int just;
  649. {
  650.   int fmt;
  651.   int prc;
  652.   struct user_fmt *ufmt;
  653.   char *bptr;
  654.   char *eptr;
  655.   int len;
  656.  
  657.   fmt = GET_FMT (cp);
  658.   if (fmt == FMT_DEF)
  659.     fmt = default_fmt;
  660.   prc = GET_PRC (fmt);
  661.   switch (fmt | PRC_FLT)
  662.     {
  663.     case FMT_GPH:
  664.     case FMT_HID:
  665.       return numb_oflo;
  666.     case FMT_DOL:
  667.       ufmt = &dol;
  668.       goto deal_fmt;
  669.  
  670.     case FMT_CMA:
  671.       ufmt = &cma;
  672.       goto deal_fmt;
  673.  
  674.     case FMT_PCT:
  675.       ufmt = &cma;
  676.       goto deal_fmt;
  677.  
  678.     case FMT_FXT:
  679.       ufmt = &fxt;
  680.       goto deal_fmt;
  681.  
  682.     case FMT_USR:
  683.       ufmt = &u[prc];
  684.       prc = ufmt->prec;
  685.       goto deal_fmt;
  686.  
  687.     case FMT_GEN:
  688.       if (prc != PRC_FLT)
  689.     return numb_oflo;
  690.       if (index (oldp, 'e') || !index (oldp, '.'))
  691.     goto handle_exp;
  692.  
  693.       ufmt = &fxt;
  694.       prc = PRC_FLT;
  695.       goto deal_fmt;
  696.  
  697.     deal_fmt:
  698.       if (prc != PRC_FLT)
  699.     return numb_oflo;
  700.       len = strlen (oldp);
  701.       bptr = (char *)strstr (oldp, ufmt->decpt);
  702.       if (!bptr)
  703.     return numb_oflo;
  704.       while (eptr = (char *)strstr (bptr + 1, ufmt->decpt))
  705.     bptr = eptr;
  706.  
  707.       if (width < bptr - oldp)
  708.     return numb_oflo;
  709.       if (bptr - oldp + strlen (ufmt->decpt) >= width)
  710.     prc = 0;
  711.       else
  712.     {
  713.       prc = width - (strlen (ufmt->decpt) + bptr - oldp);
  714.     }
  715.       bptr = pr_flt (cp->cell_flt, ufmt, -prc);
  716.       len = strlen (bptr);
  717.       if (len > width && prc > 0)
  718.     {
  719.       bptr = pr_flt (cp->cell_flt, ufmt, -(prc - 1));
  720.       len = strlen (bptr);
  721.     }
  722.       if (len > width)
  723.     return numb_oflo;
  724.       break;
  725.  
  726.     case FMT_EXP:
  727.     handle_exp:
  728.       {
  729.     double f;
  730.  
  731.     f = fabs (cp->cell_flt);
  732.     if (f > 9.99999e99 || f < 1e-99)
  733.       len = width - 7;
  734.     else            /* if(f>9.9999999e9 || f<1e-9) */
  735.       len = width - 6;
  736.     /* else
  737.                 len=width-5; */
  738.     if (cp->cell_flt < 0)
  739.       --len;
  740.     if (len > 0)
  741.       {
  742.         sprintf (oldp, "%.*e", len, cp->cell_flt);
  743.         len = strlen (oldp);
  744.         if (len <= width)
  745.           {
  746.         bptr = oldp;
  747.         break;
  748.           }
  749.       }
  750.       }
  751.       return numb_oflo;
  752. #ifdef TEST
  753.     default:
  754.       panic ("Unknown format %d in adjust_prc()", fmt);
  755.       bptr = 0;
  756.       len = 0;
  757.       break;
  758. #endif
  759.     }
  760.  
  761.   /* If we get here, bptr points to a a string of len characters
  762.        (len<=width) that we want to output */
  763.   if (len < smallwid)
  764.     {
  765.       if (just == JST_RGT || just == JST_CNT)
  766.     {
  767.       int n;
  768.  
  769.       n = (just == JST_RGT) ? smallwid - len : (1 + smallwid - len) / 2;
  770.       for (;;)
  771.         {
  772.           bptr[len + n] = bptr[len];
  773.           if (len-- == 0)
  774.         break;
  775.         }
  776.       while (n-- >= 0)
  777.         bptr[n] = ' ';
  778.     }
  779.     }
  780.   return bptr;
  781. }
  782.  
  783.  
  784. void
  785. set_usr_stats (usr_n, usr_buf)
  786.      int usr_n;
  787.      char **usr_buf;
  788. {
  789.   int len;
  790.   int i;
  791.   char *p_in, *p_out;
  792.  
  793.   len = 0;
  794.   for (i = 0; i < 7; i++)
  795.     len += strlen (usr_buf[i]);
  796.   u[usr_n].p_hdr = ck_malloc (len + 7);
  797.   p_out = u[usr_n].p_hdr;
  798.   if (usr_buf[0][0])
  799.     {
  800.       p_in = usr_buf[0];
  801.       while (*p_out++ = *p_in++)
  802.     ;
  803.     }
  804.   else
  805.     *p_out++ = '\0';
  806.  
  807.   if (usr_buf[1][0])
  808.     {
  809.       p_in = usr_buf[1];
  810.       u[usr_n].n_hdr = p_out;
  811.       while (*p_out++ = *p_in++)
  812.     ;
  813.     }
  814.   else
  815.     u[usr_n].n_hdr = 0;
  816.  
  817.   if (usr_buf[2][0])
  818.     {
  819.       p_in = usr_buf[2];
  820.       u[usr_n].p_trl = p_out;
  821.       while (*p_out++ = *p_in++)
  822.     ;
  823.     }
  824.   else
  825.     u[usr_n].p_trl = 0;
  826.  
  827.   if (usr_buf[3][0])
  828.     {
  829.       p_in = usr_buf[3];
  830.       u[usr_n].n_trl = p_out;
  831.       while (*p_out++ = *p_in++)
  832.     ;
  833.     }
  834.   else
  835.     u[usr_n].n_trl = 0;
  836.  
  837.   if (usr_buf[4][0])
  838.     {
  839.       p_in = usr_buf[4];
  840.       u[usr_n].zero = p_out;
  841.       while (*p_out++ = *p_in++)
  842.     ;
  843.     }
  844.   else
  845.     u[usr_n].zero = 0;
  846.  
  847.   if (usr_buf[5][0])
  848.     {
  849.       p_in = usr_buf[5];
  850.       u[usr_n].comma = p_out;
  851.       while (*p_out++ = *p_in++)
  852.     ;
  853.     }
  854.   else
  855.     u[usr_n].comma = 0;
  856.  
  857.   if (usr_buf[6][0])
  858.     {
  859.       p_in = usr_buf[6];
  860.       u[usr_n].decpt = p_out;
  861.       while (*p_out++ = *p_in++)
  862.     ;
  863.     }
  864.   else
  865.     u[usr_n].decpt = 0;
  866.  
  867.   if (!stricmp (usr_buf[7], "float") || !stricmp (usr_buf[7], "f"))
  868.     u[usr_n].prec = 15;
  869.   else
  870.     u[usr_n].prec = astol (&usr_buf[7]);
  871.  
  872.   u[usr_n].scale = astof (&usr_buf[8]);
  873. }
  874.  
  875. #ifdef __STDC__
  876. int
  877. usr_set_fmts (void)
  878. #else
  879. int
  880. usr_set_fmts ()
  881. #endif
  882. {
  883.   int n;
  884.   int ret = 0;
  885.  
  886.   for (n = 0; n < 16; n++)
  887.     if (u[n].p_hdr)
  888.       ret |= 1 << n;
  889.   return ret;
  890. }
  891.  
  892. void
  893. get_usr_stats (usr_num, usr_buf)
  894.      int usr_num;
  895.      char **usr_buf;
  896. {
  897.   static char buf1[30];
  898.   static char buf2[30];
  899.   static char NullStr[] = "";
  900.  
  901.   usr_buf[0] = u[usr_num].p_hdr ? u[usr_num].p_hdr : NullStr;
  902.   usr_buf[1] = u[usr_num].n_hdr ? u[usr_num].n_hdr : NullStr;
  903.   usr_buf[2] = u[usr_num].p_trl ? u[usr_num].p_trl : NullStr;
  904.   usr_buf[3] = u[usr_num].n_trl ? u[usr_num].n_trl : NullStr;
  905.   usr_buf[4] = u[usr_num].zero ? u[usr_num].zero : NullStr;
  906.   usr_buf[5] = u[usr_num].comma ? u[usr_num].comma : NullStr;
  907.   usr_buf[6] = u[usr_num].decpt ? u[usr_num].decpt : NullStr;
  908.   if (u[usr_num].prec == 15)
  909.     usr_buf[7] = "float";
  910.   else
  911.     {
  912.       sprintf (buf1, "%u", u[usr_num].prec);
  913.       usr_buf[7] = buf1;
  914.     }
  915.   sprintf (buf2, "%.12g", u[usr_num].scale);
  916.   usr_buf[8] = buf2;
  917. }
  918.  
  919. /* Functions for printing out the names of cells and ranges */
  920.  
  921. #if __STDC__
  922. char *
  923. cell_name (CELLREF rr, CELLREF cc)
  924. #else
  925. char *
  926. cell_name (rr, cc)
  927.      CELLREF rr;
  928.      CELLREF cc;
  929. #endif
  930. {
  931.   static char strs[2][20];
  932.   static num = 0;
  933.   char *ptr;
  934.  
  935.   num = num ? 0 : 1;
  936.  
  937.   if (a0)
  938.     {
  939.       ptr = &strs[num][9];
  940.       sprintf (ptr, "%u", rr);
  941.       if (cc < MIN_COL + 26)
  942.     *--ptr = 'A' - MIN_COL + cc;
  943. #if MAX_COL>702
  944.       else if (cc < MIN_COL + 702)
  945.     {
  946.       cc -= MIN_COL + 26;
  947.       *--ptr = 'A' + cc % 26;
  948.       *--ptr = 'A' + cc / 26;
  949.     }
  950.       else if (cc < MIN_COL + 18278)
  951.     {
  952.       cc -= MIN_COL + 702;
  953.       *--ptr = 'A' + cc % 26;
  954.       cc /= 26;
  955.       *--ptr = 'A' + cc % 26;
  956.       *--ptr = 'A' + cc / 26;
  957.     }
  958.       else
  959.     {
  960.       cc -= MIN_COL + 18278;
  961.       *--ptr = 'A' + cc % 26;
  962.       cc /= 26;
  963.       *--ptr = 'A' + cc % 26;
  964.       cc /= 26;
  965.       *--ptr = 'A' + cc % 26;
  966.       *--ptr = 'A' + cc / 26;
  967.     }
  968. #else
  969.       else
  970.     {
  971.       cc -= MIN_COL + 26;
  972.       *--ptr = 'A' + cc % 26;
  973.       *--ptr = 'A' + cc / 26;
  974.     }
  975. #endif
  976.     }
  977.   else
  978.     {
  979.       ptr = &strs[num][0];
  980.       sprintf (ptr, "r%uc%u", rr, cc);
  981.     }
  982.   return ptr;
  983. }
  984.  
  985. char *
  986. range_name (rng)
  987.      struct rng *rng;
  988. {
  989.   CELLREF lr, lc, hr, hc;
  990.   static char buf[2][40];
  991.   static num;
  992.   char *ptr;
  993.  
  994.   ptr = &buf[num][0];
  995.   num = num ? 0 : 1;
  996.  
  997.   lr = rng->lr;
  998.   lc = rng->lc;
  999.   hr = rng->hr;
  1000.   hc = rng->hc;
  1001.  
  1002.   if (a0)
  1003.     sprintf (ptr, "%s:%s", cell_name (lr, lc), cell_name (hr, hc));
  1004.   else
  1005.     {
  1006.       if (lr == hr && lc == hc)
  1007.     sprintf (ptr, "r%uc%u", lr, lc);
  1008.       else if (lr == hr && lc != hc)
  1009.     sprintf (ptr, "r%uc%u:%u", lr, lc, hc);
  1010.       else if (lr != hr && lc == hc)
  1011.     sprintf (ptr, "r%u:%uc%u", lr, hr, lc);
  1012.       else
  1013.     sprintf (ptr, "r%u:%uc%u:%u", lr, hr, lc, hc);
  1014.     }
  1015.   return ptr;
  1016. }
  1017.  
  1018.  
  1019. #if __STDC__
  1020. char *
  1021. col_to_str (CELLREF col)
  1022. #else
  1023. char *
  1024. col_to_str (col)
  1025.      CELLREF col;
  1026. #endif
  1027. {
  1028.   static char strs[2][10];
  1029.   static num;
  1030.   char *ptr;
  1031.  
  1032.   ptr = &strs[num][9];
  1033.   num = num ? 0 : 1;
  1034.  
  1035.   if (col < MIN_COL + 26)
  1036.     *--ptr = 'A' - MIN_COL + col;
  1037. #if MAX_COL>702
  1038.   else if (col < MIN_COL + 702)
  1039.     {
  1040.       col -= MIN_COL + 26;
  1041.       *--ptr = 'A' + col % 26;
  1042.       *--ptr = 'A' + col / 26;
  1043.     }
  1044.   else if (col < MIN_COL + 18278)
  1045.     {
  1046.       col -= MIN_COL + 702;
  1047.       *--ptr = 'A' + col % 26;
  1048.       col /= 26;
  1049.       *--ptr = 'A' + col % 26;
  1050.       *--ptr = 'A' + col / 26;
  1051.     }
  1052.   else
  1053.     {
  1054.       col -= MIN_COL + 18278;
  1055.       *--ptr = 'A' + col % 26;
  1056.       col /= 26;
  1057.       *--ptr = 'A' + col % 26;
  1058.       col /= 26;
  1059.       *--ptr = 'A' + col % 26;
  1060.       *--ptr = 'A' + col / 26;
  1061.     }
  1062. #else
  1063.   else
  1064.     {
  1065.       col -= MIN_COL + 26;
  1066.       *--ptr = 'A' + col % 26;
  1067.       *--ptr = 'A' + col / 26;
  1068.     }
  1069. #endif
  1070.   return ptr;
  1071. }
  1072.  
  1073. void
  1074. clear_spreadsheet ()
  1075. {
  1076.   int n;
  1077.  
  1078.   flush_everything ();
  1079.   /* flush_widths(); */
  1080.   flush_all_timers ();
  1081.   for (n = 0; n < 16; n++)
  1082.     {
  1083.       if (u[n].p_hdr)
  1084.     {
  1085.       free (u[n].p_hdr);
  1086.       u[n].p_hdr = 0;
  1087.       u[n].prec = PRC_FLT;
  1088.       u[n].scale = 1;
  1089.     }
  1090.     }
  1091.   default_width = saved_default_width;
  1092.   default_height = saved_default_height;
  1093.   default_jst = JST_LFT;
  1094.   default_fmt = FMT_GEN;
  1095.   default_lock = LCK_UNL;
  1096. }
  1097.